﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

namespace eBrain
{
    public partial class Exp_Gambling : Experiment
    {
        //--------------------------------------------
        //   CardGambling
        //--------------------------------------------
        String BackGroundString;
        int ActualMoney = 0;
        int DefaultMoney, GivenMoney, MaxMoney;
        int infoRectX, infoRectY, infoRectW, infoRectH;
        int WinMoney, LoseMoney;
        public String DefaultWinString, DefaultLoseString, DefaultCurrency, DefaultAllLostString, DefaultBrokenString;
        public String DefaultMessage;
        public int DefaultFontSize;
        public CardGamblingStatus CGStatus = CardGamblingStatus.WaitingForSelection;
        public enum CardGamblingStatus { WaitingForSelection, PositiveFeedBack, NegativeFeedback, LostAllMoney, Broken }; //Stage0 = in attesa della selezione; Stage1 = rinforzo positivo; //Stage2 = rinforzo negativo; //Stage3 = in caso di perdita di tutti i soldi

        public Deck[] deck;
        private int A = 0, B = 1, C = 2, D = 3;
        public XmlNodeList decks;
        public int NumOfTrials;
        public int CardsInDeck;
        //public enum Decks { A, B, C, D };
        public Exp_Gambling(TestControlWindow _tcw, ExperimentMainForm _expw)//, int _w, int _h)
            : base(_tcw, _expw)//, _w, _h) 
        { }

        public Exp_Gambling(ExperimentMainForm _expw, string datapath, string logpath, string sInputMode)
            : base(_expw, datapath, logpath, sInputMode)//, _w, _h) 
        { }


        public override void CustomInit()
        {
            ActualMoney = 0;
            deck = new Deck[4];
            deck[A] = new Deck();
            deck[B] = new Deck();
            deck[C] = new Deck();
            deck[D] = new Deck();
        }

        public override void CustomXMLLoad(XmlDocument xmldoc)
        {
            BackGroundString = xmldoc.SelectSingleNode("Experiment/BackgroundText").InnerText;
            infoRectX = int.Parse(xmldoc.SelectSingleNode("Experiment/InfoRectangleX").InnerText.Replace(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PercentSymbol, ""));
            infoRectY = int.Parse(xmldoc.SelectSingleNode("Experiment/InfoRectangleY").InnerText.Replace(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PercentSymbol, ""));
            infoRectW = int.Parse(xmldoc.SelectSingleNode("Experiment/InfoRectangleW").InnerText.Replace(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PercentSymbol, ""));
            infoRectH = int.Parse(xmldoc.SelectSingleNode("Experiment/InfoRectangleH").InnerText.Replace(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PercentSymbol, ""));
            DefaultWinString = xmldoc.SelectSingleNode("Experiment/DefaultWinText").InnerText;
            DefaultAllLostString = xmldoc.SelectSingleNode("Experiment/DefaultAllLostText").InnerText;
            DefaultBrokenString = xmldoc.SelectSingleNode("Experiment/DefaultBrokenText").InnerText;
            
            DefaultLoseString = xmldoc.SelectSingleNode("Experiment/DefaultLoseText").InnerText;
            DefaultCurrency = xmldoc.SelectSingleNode("Experiment/DefaultCurrency").InnerText;
            DefaultMessage = xmldoc.SelectSingleNode("Experiment/DefaultMessage").InnerText;
            DefaultFontSize = int.Parse(xmldoc.SelectSingleNode("Experiment/DefaultFontSize").InnerText);

            DefaultMoney = int.Parse(xmldoc.SelectSingleNode("Experiment/DefaultMoney").InnerText);
            GivenMoney = DefaultMoney;
            MaxMoney = int.Parse(xmldoc.SelectSingleNode("Experiment/MaxMoney").InnerText);
            ActualMoney = DefaultMoney;

            decks = xmldoc.SelectNodes("Experiment/DECKS/DECK");
            NumOfTrials = int.Parse(xmldoc.SelectSingleNode("Experiment/NumberOfTrials").InnerText);
            CardsInDeck = int.Parse(xmldoc.SelectSingleNode("Experiment/CardsInDeck").InnerText);
            //base.CustomXMLLoad(xmldoc);

            try{
            //carico i mazzi di carte
            for (int i = 0; i < 4; i++)
            {
                string filepath = decks[i].SelectSingleNode("path").InnerText;
                using (StreamReader r = new StreamReader(filepath))
                {
                    string line;
                    while((line = r.ReadLine())!= null)
                    {
                        deck[i].AddLine(line);
                    }

                }
            }
            
            }
                catch(Exception ex){
                    MessageBox.Show("Gambling XML Custom Load Error: " + ex.InnerException + " - " + ex.Source.ToString());
                }
        }

        /// <summary>
        /// UpdateCanvas : Aggiorna il canovaccio principale
        /// </summary>
        public override void UpdateCanvas()
        {

            int x, y, w, h, x0, y0, w1, h1;
            string sx, sy;
            string imgfile = "";
            string text = "";

            UpdateCanvasMtx.WaitOne();

            //myExpW.LockCanvasUserCopy();
            Graphics CanvasGraphics = Graphics.FromImage(WorkingCanvas);
            CanvasGraphics.Clear(bkgrnd);


            //Le ROI sono costanti, seleziono il Trial
            UpdateConstantROIList();

            try
            {

                if (ExpInputMode != InputMode.P300Speller)
                {


                    //XmlNodeList TrialROIList;
                    //if (bTrainingMode)
                    //    TrialROIList = TrainingTrials.Item(ActualTrialNumber).SelectNodes("ROIs/ROI");
                    //else
                    //    TrialROIList = Trials.Item(ActualTrialNumber).SelectNodes("ROIs/ROI");

                    for (int k = 0; k < ROIs.Count; k++)
                    {
                        //Calcolo i dati geometrici
                        w = int.Parse(ROIs.Item(k).SelectSingleNode("w").InnerText.ToString());
                        h = int.Parse(ROIs.Item(k).SelectSingleNode("h").InnerText.ToString());

                        sx = ROIs.Item(k).SelectSingleNode("x").InnerText.ToString();
                        sy = ROIs.Item(k).SelectSingleNode("y").InnerText.ToString();


                        x = int.Parse(sx.Replace(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PercentSymbol, ""));
                        y = int.Parse(sy.Replace(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PercentSymbol, ""));

                        x0 = (x * ScreenWidth) / 100;
                        y0 = (y * ScreenHeight) / 100;
                        //x =  x0 - w / 2;
                        //y =  y0 - h / 2;


                        //<DataViewer> 
                        if (bEyelinkConnected)
                        {
                            string sID = ROIs.Item(k).SelectSingleNode("ID").InnerText.ToString();

                            ET.SendMessage("!V IAREA RECTANGLE " + (k + 1).ToString() + " " +
                                 (x0 - w / 2).ToString() + " " +
                                 (y0 - h / 2).ToString() + " " +
                                 (x0 + w / 2).ToString() + " " +
                                 (y0 + h / 2).ToString() + " " +
                                 sID);
                            //el.sendMessage
                        }

                        //if (bConstantROIImages)
                            imgfile = ROIs.Item(k).SelectSingleNode("img").InnerText.ToString();
                        //else
                        //{
                        //    imgfile = TrialROIList.Item(k).SelectSingleNode("img").InnerText.ToString();
                        //    text = TrialROIList.Item(k).SelectSingleNode("text").InnerText.ToString();
                        //    //ROIs.Item(k).Value = TrialROIList.Item(k).Value;
                        //}

                        if (imgfile != "")
                        {
                            Image myImag = Image.FromFile(sImagePath + imgfile);
                            w1 = myImag.Width;
                            h1 = myImag.Height;
                            x = x0 - w1 / 2;
                            y = y0 - h1 / 2;

                            //myImag.HorizontalResolution

                            CanvasGraphics.DrawImageUnscaled(myImag, x, y);

                            //<DataViewer> se è connesso l'eyetracker, spedisco il comando per disegnare l'mmagine nel dataviewer
                            if (bEyelinkConnected)
                            {
                                ET.SendMessage("!V IMGLOAD TOP_LEFT " + sImagePath + imgfile + x.ToString() + " " + y.ToString());
                            }

                            //e.Graphics.DrawLine(new Pen(frgrnd), x0, 0, x0, 800);
                            //graphicsObj.DrawLine(myPen, 0, 0, 1000, 400);
                        }
                        else if (text != "")
                        {
                            x = x0 - w / 2;
                            y = y0 - h / 2;

                            using (Font font1 = new Font("Arial", 30, FontStyle.Regular, GraphicsUnit.Point))
                            {
                                Rectangle rect1 = new Rectangle(x, y, w, h);
                                TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter;
                                TextRenderer.DrawText(CanvasGraphics, text, font1, rect1, frgrnd, flags);
                                //e.Graphics.DrawString(text, font1, Brushes.Blue, rectF1,);
                                //e.Graphics.DrawRectangle(Pens.White, Rectangle.Round(rectF1));
                            }
                        }
                    }
                }

                //Se sto facendo il gambling, allora devo aggiornare anche un po' di altre cose


                int w2;//xf, yf, 
                int wt, ht;
                int MajorSteps = 3;
                int MinorSteps = 6;

                x0 = (ScreenWidth * infoRectX) / 100;
                y0 = (ScreenHeight * infoRectY) / 100;
                w = (ScreenWidth * infoRectW) / 100;
                h = (ScreenHeight * infoRectH) / 100;
                w1 = (ActualMoney * w) / MaxMoney;
                w2 = (GivenMoney * w) / MaxMoney;
                Rectangle R1 = new Rectangle(x0, y0, w1, h / 2);
                Rectangle R2 = new Rectangle(x0, y0 + h / 2, w2, h / 2);
                SolidBrush RedBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Red);
                SolidBrush GreenBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Green);
                Pen BorderPen = new Pen(frgrnd);

                CanvasGraphics.FillRectangle(GreenBrush, R1);
                CanvasGraphics.FillRectangle(RedBrush, R2);
                CanvasGraphics.DrawRectangle(BorderPen, x0, y0, w, h);

                int MajorDelta = MaxMoney / MajorSteps;
                int MinorDelta = MaxMoney / MinorSteps;

                wt = 70;
                ht = 15;
                y = y0 - 15 - ht / 2;

                //Disegno la linea tra le barre
                CanvasGraphics.DrawLine(BorderPen, x0, y0 + h / 2, x0 + w, y0 + h / 2);

                for (int i = 0; i <= MajorSteps; i++)
                {
                    x = x0 + (i * w / MajorSteps) - wt / 2;
                    using (Font font1 = new Font("Arial", 10, FontStyle.Regular, GraphicsUnit.Point))
                    {
                        text = DefaultCurrency + " " + (i * MajorDelta).ToString();
                        Rectangle rect1 = new Rectangle(x, y, wt, ht);
                        Rectangle rect2 = new Rectangle(x, y + h + 2 * ht, wt, ht);
                        TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter;
                        TextRenderer.DrawText(CanvasGraphics, text, font1, rect1, frgrnd, flags);
                        TextRenderer.DrawText(CanvasGraphics, text, font1, rect2, frgrnd, flags);

                        CanvasGraphics.DrawLine(BorderPen, x0 + (i * w / MajorSteps), y0 - 5, x0 + (i * w / MajorSteps), y0 + 5);
                        CanvasGraphics.DrawLine(BorderPen, x0 + (i * w / MajorSteps), y0 + h - 5, x0 + (i * w / MajorSteps), y0 + h + 5);
                    }
                }

                for (int i = 0; i <= MinorSteps; i++)
                {
                    CanvasGraphics.DrawLine(BorderPen, x0 + (i * w / MinorSteps), y0 - 3, x0 + (i * w / MinorSteps), y0 + 3);
                    CanvasGraphics.DrawLine(BorderPen, x0 + (i * w / MinorSteps), y0 + h - 3, x0 + (i * w / MinorSteps), y0 + h + 3);
                }


                switch (CGStatus)
                {
                    case CardGamblingStatus.WaitingForSelection:

                        using (Font font1 = new Font("Arial", DefaultFontSize, FontStyle.Regular, GraphicsUnit.Point))
                        {
                            text = DefaultMessage;
                            Rectangle rect1 = new Rectangle(x0, y0 + h + 100, w, 40);
                            TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter;
                            TextRenderer.DrawText(CanvasGraphics, text, font1, rect1, frgrnd, flags);
                        }
                        break;

                    case CardGamblingStatus.PositiveFeedBack:

                        using (Font font1 = new Font("Arial", DefaultFontSize, FontStyle.Regular, GraphicsUnit.Point))
                        {
                            text = DefaultWinString + " " + DefaultCurrency + " " + WinMoney.ToString() + "!!!";
                            Rectangle rect1 = new Rectangle(x0, y0 + h + 40, 200, 40);
                            TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter;
                            TextRenderer.DrawText(CanvasGraphics, text, font1, rect1, frgrnd, flags);
                        }
                        break;

                    case CardGamblingStatus.NegativeFeedback:

                        using (Font font1 = new Font("Arial", DefaultFontSize, FontStyle.Regular, GraphicsUnit.Point))
                        {
                            text = DefaultLoseString + " " + DefaultCurrency + " " + LoseMoney.ToString() + "!!!";
                            Rectangle rect1 = new Rectangle(x0 + w - 200, y0 + h + 40, 200, 40);
                            TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter;
                            TextRenderer.DrawText(CanvasGraphics, text, font1, rect1, frgrnd, flags);
                        }
                        break;

                    case CardGamblingStatus.LostAllMoney:

                        using (Font font1 = new Font("Arial", DefaultFontSize, FontStyle.Regular, GraphicsUnit.Point))
                        {
                            text = DefaultAllLostString;
                            Rectangle rect1 = new Rectangle(x0, y0 + h + 100, w, 40);
                            TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter;
                            TextRenderer.DrawText(CanvasGraphics, text, font1, rect1, frgrnd, flags);
                        }
                        break;

                    case CardGamblingStatus.Broken:

                        using (Font font1 = new Font("Arial", DefaultFontSize, FontStyle.Regular, GraphicsUnit.Point))
                        {
                            text = DefaultBrokenString;
                            Rectangle rect1 = new Rectangle(x0, y0 + h + 100, w, 40);
                            TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter;
                            TextRenderer.DrawText(CanvasGraphics, text, font1, rect1, frgrnd, flags);
                        }
                        break;

                    default:
                        break;
                }

                CanvasGraphics.Dispose();
                myExpW.CopyImage(WorkingCanvas);
                //myExpW.UnlockCanvasUserCopy();

                UpdateCanvasMtx.ReleaseMutex();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Update Canvas Error: " + ex.Message.ToString() + "\r\n" + ex.StackTrace);
            }
        }

        public override void Custom_DoNextTrial()
        {
            UpdateCanvas();
            myExpW.Invalidate();

            //Thread.Sleep(100);
            if (!bStandAlone)
                PaintCanvasOnTCW();
        }

        public override void StartTrials(bool TrainingMode)
        {
            bool go_on = false;
            try
            {
                //myLog.Log("Start Trials: begin");

                //azzero la somma cumulativa dei ritardi (TODO: da rivedere insieme alla struttura dei risultati resultlist) 
                CumSumTiming = 0;

                //azzero il numero di timeout
                NumOfTimeout = 0;

                //Azzero il punteggio dei Trial
                TrialScore = 0;

                bTrainingMode = TrainingMode;

                if (!bStandAlone)
                {
                        myTCW.updateTrialsNumbers(0, NumOfTrials);
                }

                ExperimentStopped = false;

                if (bDoCountdown)
                {
                    CountDown(3, 800);
                    //StartPeriodicTimer();

                    if (bUseSounds)
                        Beep(2000, 500);
                }

                UpdateCanvas();
                //if (bUseAudioCues)
                //    PlayCue(); 

                //cancello lo schermo e le ultime informazioni circa le parti da evidenziare
                myExpW.ClearScreen(bkgrnd);

                myExpW.HighlightEnabled = true;
                myExpW.Invalidate();
                //UpdateGraphics();
                //Thread.Sleep(100);
                if (!bStandAlone)
                    PaintCanvasOnTCW();

                //StartPeriodicTimer();

                EndOfTrials = false;

                if (ExpInputMode == InputMode.Eyetracker)
                {
                    //Aggiorno le ROI sullo schermo 
                    UpdateHostROI();
                    ET.StartRecording();
                }

                myExpW.SetSmoothPursuitMode((ExperimentType == _ExperimentType.SmoothPursuit));

                //myLog.Log("Start Trials: end");

                go_on = true;
            }
            catch (Exception ex)
            {
                myLog.Log("StartTrials error: " + ex.Message.ToString() + " - " + ex.Source.ToString());
                MessageBox.Show("StartTrials error: " + ex.Message.ToString() + " - " + ex.Source.ToString());
                go_on = false;
            }
            finally
            {
                //Se posso procedere, passo al primo Trial
                if (go_on && exp_status != ExperimentStatus.Ending)
                    DoNextTrial();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public override void DoNextTrial()
        {
            try
            {
                myLog.Log("DoNextTrial: trial = " + ActualTrialNumber.ToString());

                //Console.WriteLine("DoNextTrial - 1");
                if (!bStandAlone)
                {
                        myExpW.Invoke(new EventHandler(delegate { myTCW.updateTrialsNumbers(ActualTrialNumber + 1, NumOfTrials); }));
                }
                Custom_DoNextTrial();

                //Aggiorno il dato relativo ai risultati
                if (!bStandAlone)
                    myExpW.Invoke(new EventHandler(delegate { myTCW.updateTrialFigures(TrialScore, NumOfTimeout); }));


                //Nel caso stia lavorando con l'ET, allora invio le opportune segnalazioni all'ET
                if (ExpInputMode == InputMode.Eyetracker && bEyelinkConnected)
                {
                    if (!bConstantRois)
                        UpdateHostROI();

                    ET_LabelTrial();
                }

                exp_status = ExperimentStatus.DoingTrials;

                GC.Collect();
                GC.WaitForPendingFinalizers();

                //Console.WriteLine("DoNextTrial - 2");
                //UpdateGraphics();

                if (ExperimentType != _ExperimentType.SmoothPursuit)
                {
                    myExpW.Invoke(new EventHandler(delegate { myExpW.Refresh(); }));
                }

                //TODO: verificare che vada bene qui 
                if (bUseAudioCues)
                    PlayCue();

                //Se sto lavorando con le BCI non faccio partire i timer (TODO: da verificare)
                if (ExpInputMode != InputMode.P300Speller)
                {

                    if (ExperimentType != _ExperimentType.SmoothPursuit)
                    {
                        //myExpW.Invoke(new EventHandler(delegate { myExpW.Refresh(); }));
                        TimeoutTimer.Start();
                    }

                    //Console.WriteLine("DoNextTrial - 3");
                    //myLog.Log("DoNextTrial: end");

                    StartPeriodicTimer();
                }

                TrialStartTimeList.Add(DateTime.Now);

                //TrialStartTime = DateTime.Now;

            }

            catch (Exception ex)
            {
                myLog.Log("DoNextTrial error: " + ex.Message.ToString() + " - " + ex.StackTrace);
                MessageBox.Show("DoNextTrial error: " + ex.Message.ToString() + " - " + ex.StackTrace);
            }
        }



        /// <summary>
        /// GEstisco la selezione che è stata richiamata dal gestore di eventi
        /// </summary>
        public override void SelectionHandler()
        {
            String s;
            int val;
            String sWin, sLose;
            int roi_selected = ROI_Selected;

            lock (myROIList)
            {
                //TODO: da verificare
                if (ExpInputMode == InputMode.P300Speller)
                {
                    s = myROIList.myRoiList[roi_selected].sItem;
                    //val = myROIList.myRoiList[roi_selected].iValue;


                    //lo segnalo all'oggetto form, con una persistenza di 1000 ms (TODO: verificare che sia adatta)
                    myExpW.UpdateSelectedArea(myROIList.myRoiList[roi_selected].x0, myROIList.myRoiList[roi_selected].y0,
                        myROIList.myRoiList[roi_selected].width, myROIList.myRoiList[roi_selected].height,
                        HighlightSelectionColor, iHighlightSelectionSize);//, 1000);

                    ////lo segnalo all'oggetto form, con una persistenza di 1000 ms (TODO: verificare che sia adatta)
                    // myExpW.Invoke(new EventHandler(delegate {
                    // myTranspLayer.UpdateP3WinSelectedArea(myROIList.myRoiList[roi_selected].x0, myROIList.myRoiList[roi_selected].y0,
                    //    myROIList.myRoiList[roi_selected].width, myROIList.myRoiList[roi_selected].height,
                    //    HighlightSelectionColor, iHighlightSelectionSize, HighlightSelectionTime);//, 1000);
                    // }));
                }
                else
                {
                    s = myROIList.GD_AreaSelected.item;
                    //val = myROIList.GD_AreaSelected.value;

                    //lo segnalo all'oggetto form, con una persistenza di 1000 ms (TODO: verificare che sia adatta)
                    myExpW.UpdateSelectedArea(myROIList.GD_AreaSelected.x, myROIList.GD_AreaSelected.y,
                        myROIList.GD_AreaSelected.w, myROIList.GD_AreaSelected.h,
                        HighlightSelectionColor, iHighlightSize);//, 1000);
                }
            }

            val = deck[roi_selected].cur_value();

            myResultList.Add(new ResultListElement(val, s, ""));

            myLog.Log("Target selected: " + s);

            //XmlNodeList SelectedNodes;

            //if (bTrainingMode)
            //    SelectedNodes = TrainingTrials.Item(ActualTrialNumber).SelectNodes("ROIs/ROI");
            //else
            //    SelectedNodes = Trials.Item(ActualTrialNumber).SelectNodes("ROIs/ROI");


            sWin = deck[roi_selected].cur_text_win(); //SelectedNodes.Item(roi_selected).SelectSingleNode("text_win").InnerText.ToString();
            sLose = deck[roi_selected].cur_text_lose(); //SelectedNodes.Item(roi_selected).SelectSingleNode("text_lose").InnerText.ToString();

            deck[roi_selected].cur_item++;

            WinMoney = int.Parse(sWin);
            if (WinMoney > 0)
            {
                CGStatus = CardGamblingStatus.PositiveFeedBack;
                UpdateCanvas();
                myExpW.Invalidate();
                Thread.Sleep(50);
                if (bUseSounds)
                    SPGambleWin.PlaySync();

                Thread.Sleep(100);
            }

            if (sLose != "")
            {
                LoseMoney = Math.Abs(int.Parse(sLose));
                if (LoseMoney > 0)
                {
                    CGStatus = CardGamblingStatus.NegativeFeedback;
                    UpdateCanvas();
                    myExpW.Invalidate();
                    Thread.Sleep(50);

                    if (bUseSounds)
                        SPGambleLose.PlaySync();

                    Thread.Sleep(100);
                }
            }

            ActualMoney += val;

            //Nel caso arrivi sotto zero, riparto da 2000
            if (ActualMoney <= 0)
            {
                ActualMoney = DefaultMoney;
                GivenMoney += DefaultMoney;
                CGStatus = CardGamblingStatus.LostAllMoney;
                myExpW.Invalidate();
                Thread.Sleep(700);
            }


            CGStatus = CardGamblingStatus.WaitingForSelection;
            myExpW.Invalidate();

            bROISelected = false;

            //resetto la roi selezionata
            ROI_Selected = RoiList.NO_ROI;

            //<DataViewer>
            if (bEyelinkConnected)
                ET.SendCommand("TRIAL_RESULT 0");

            if (bTrainingMode)
            {
                if (++ActualTrialNumber >= TrainingTrials.Count)
                    FromTrainingToTrials();
                else
                {
                    DoNextTrial();
                }
            }
            else
            {
                if (++ActualTrialNumber >= NumOfTrials)
                {
                    ActualTrialNumber = NumOfTrials - 1;
                    EndOfTrials = true;

                    EndOfTest();
                    //SaveResults();
                    //EndOfTest();
                }
                else
                {
                    //TODO: mettere a posto perchp qui non va benissimo - solo per prova
                    DoNextTrial();
                    //UpdateCanvas();
                    //this.Invalidate();
                }
            }
        }


        public override void TimeoutTimer_Elapsed(object obj, EventArgs e)
        {

            myResultList.Add(new ResultListElement(0, "T", "Timeout"));

            NumOfTimeout++;

            TimeoutTimer.Stop();
            StopPeriodicTimer();

            //NumOfLetters++;

            myLog.Log("Trial " + ActualTrialNumber.ToString() + " Timout : ");

            if (bUseSounds)
            {
                //SoundPlayer sp = new SoundPlayer(Properties.Resources.timeout_future);
                SPTimeout.Play();
            }

            //<DataViewer>
            if (bEyelinkConnected)
                ET.SendCommand("TRIAL_RESULT 0");

                if (++ActualTrialNumber >= NumOfTrials )
                {
                    ActualTrialNumber = Trials.Count - 1;
                    EndOfTrials = true;

                    //SaveResults();
                    EndOfTest();
                }
                else
                {
                    DoNextTrial();
                }
            
        }

        public override void UpdateConstantROIList()
        {

            int x, y, x0, y0, w, h;
            string sx, sy;
            bool active;
            string item;
            int value;

            try
            {

                //lock (RoiListLock)
                //{
                //RoiMutex.WaitOne();
                lock (myROIList)
                    myROIList.myRoiList.Clear();

                //RoiMutex.ReleaseMutex();

                for (int k = 0; k < ROIs.Count; k++)
                {
                    //Calcolo i dati geometrici


                    w = int.Parse(ROIs.Item(k).SelectSingleNode("w").InnerText.ToString());
                    h = int.Parse(ROIs.Item(k).SelectSingleNode("h").InnerText.ToString());

                    sx = ROIs.Item(k).SelectSingleNode("x").InnerText.ToString();
                    sy = ROIs.Item(k).SelectSingleNode("y").InnerText.ToString();

                    if (sx.Contains(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PercentSymbol))
                    {
                        x = int.Parse(sx.Replace(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PercentSymbol, ""));
                        x0 = (x * ScreenWidth) / 100 - w / 2;
                    }
                    else
                        x0 = int.Parse(sx) - w / 2;

                    if (sy.Contains(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PercentSymbol))
                    {
                        y = int.Parse(sy.Replace(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PercentSymbol, ""));
                        y0 = (y * ScreenHeight) / 100 - h / 2;
                    }
                    else
                        y0 = int.Parse(sy) - h / 2;


                    //x0 = (x * myCanvas.Width) / 100 - w / 2;
                    //y0 = (y * myCanvas.Height) / 100 - h / 2;


                    active = bool.Parse(ROIs.Item(k).SelectSingleNode("active").InnerText.ToString());
                    item = ROIs.Item(k).SelectSingleNode("item").InnerText.ToString();

                    value = deck[k].cur_value();
                    //if (ActROIs.Item(k).SelectSingleNode("value").InnerText.ToString() != "")
                    //    value = int.Parse(ActROIs.Item(k).SelectSingleNode("value").InnerText.ToString());
                    //else
                    //    value = 0;
                    //ROIs.Item(k).SelectSingleNode("value").InnerText.ToString());

                    string sID = ROIs.Item(k).SelectSingleNode("ID").InnerText;
                    //RoiMutex.WaitOne();
                    lock (myROIList)
                        myROIList.AddElement(x0, y0, w, h, active, sID, item, value);
                    //RoiMutex.ReleaseMutex();
                }
                //}
            }
            catch (Exception ex)
            {
                MessageBox.Show("UpdateConstantROIList error: " + ex.Message + " - " + ex.StackTrace);
            }
        }

        //public override void SelectionHandler(string result)
        //{
        //    String s;
        //    int val;
        //    String sWin, sLose;
        //    //int ROI_Selected;
        //    string[] sa;

        //    try
        //    {
        //        if (result.Contains("<"))
        //        {
        //            sa = result.Split('<');
        //            result = sa[0];
        //        }
        //        myLog.Log("Selection Handler - Target selected: " + result);

        //        //if (bUseSounds)
        //        //{
        //        //    SPSelection.PlaySync();
        //        //    Thread.Sleep(50);
        //        //}

        //        if ("abcdefghilmnopqrstuvz".Contains(result.ToLower()))
        //            ROI_Selected = "abcdefghilmnopqrstuvz".IndexOf(result.ToLower());
        //        else
        //            ROI_Selected = int.Parse(result);

        //        val = myROIList.myRoiList[ROI_Selected].iValue;

        //        myResultList.Add(new ResultListElement(val, result, ""));

        //        //NumOfLetters++;

        //        //myLog.Log("Target selected: " + s);

        //        XmlNodeList SelectedNodes;

        //        if (bTrainingMode)
        //            SelectedNodes = TrainingTrials.Item(ActualTrialNumber).SelectNodes("ROIs/ROI");
        //        else
        //            SelectedNodes = Trials.Item(ActualTrialNumber).SelectNodes("ROIs/ROI");

        //        sWin = SelectedNodes.Item(ROI_Selected).SelectSingleNode("text_win").InnerText.ToString();
        //        sLose = SelectedNodes.Item(ROI_Selected).SelectSingleNode("text_lose").InnerText.ToString();

        //        WinMoney = int.Parse(sWin);
        //        if (WinMoney > 0)
        //        {
        //            CGStatus = CardGamblingStatus.stage1;
        //            UpdateCanvas();
        //            myExpW.Invalidate();
        //            Thread.Sleep(50);
        //            if (bUseSounds)
        //                SPGambleWin.PlaySync();

        //            Thread.Sleep(100);
        //        }

        //        if (sLose != "")
        //        {
        //            LoseMoney = Math.Abs(int.Parse(sLose));
        //            if (LoseMoney > 0)
        //            {
        //                CGStatus = CardGamblingStatus.stage2;
        //                UpdateCanvas();
        //                myExpW.Invalidate();
        //                Thread.Sleep(50);

        //                if (bUseSounds)
        //                    SPGambleLose.PlaySync();

        //                Thread.Sleep(100);
        //            }
        //        }
        //        ActualMoney += val;

        //        //Nel caso arrivi sotto zero, riparto da 2000
        //        if (ActualMoney <= 0)
        //        {
        //            ActualMoney = DefaultMoney;
        //            GivenMoney += DefaultMoney;
        //            CGStatus = CardGamblingStatus.stage3;
        //            myExpW.Invalidate();
        //            Thread.Sleep(3000);
        //        }


        //        CGStatus = CardGamblingStatus.stage0;
        //        myExpW.Invalidate();

        //        bROISelected = false;

        //        //resetto la roi selezionata
        //        ROI_Selected = RoiList.NO_ROI;

        //        //<DataViewer>
        //        if (bEyelinkConnected)
        //            ET.SendCommand("TRIAL_RESULT 0");

        //        if (bTrainingMode)
        //        {
        //            if (++ActualTrialNumber >= TrainingTrials.Count)
        //                FromTrainingToTrials();
        //            else
        //            {

        //                DoNextTrial();
        //            }

        //        }
        //        else
        //        {
        //            if (++ActualTrialNumber >= Trials.Count)
        //            {
        //                ActualTrialNumber = Trials.Count - 1;
        //                EndOfTrials = true;

        //                EndOfTest();
        //                //SaveResults();
        //                //EndOfTest();
        //            }
        //            else
        //            {
        //                //TODO: mettere a posto perchp qui non va benissimo - solo per prova
        //                DoNextTrial();
        //                //UpdateCanvas();
        //                //this.Invalidate();
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        MessageBox.Show("SelectionHandler error:" + ex.Message + " " + ex.Source.ToString());

        //    }

        //}
    }
}

public class Deck
{
    public int cur_item;
    public List<String> text_win;
    public List<String> text_lose;
    public List<int> value;
    public int MaxNumItems;

    public Deck()
    {
        text_win = new List<string>();
        text_lose = new List<string>();
        value = new List<int>();
        cur_item = 0;
        MaxNumItems = 0;
    }

    public void AddItem(String sw, String sl, int val)
    {
        text_win.Add(sw);
        text_lose.Add(sl);
        value.Add(val);
        MaxNumItems++;
    }

    public void ResetCounter()
    {
        cur_item = 0;
    }
    public void AddLine(String sline) 
    {

        string[] ssplit = sline.Split(';');
        
        if(ssplit.Length >= 2){
            AddItem(ssplit[0], ssplit[1], int.Parse(ssplit[0]) + int.Parse(ssplit[1]));
        }
    }

    public string cur_text_win()
    {
        if (cur_item >= 0 && cur_item < MaxNumItems)
            return text_win[cur_item];
        else
            return "";
    }

    public string cur_text_lose()
    {
        if (cur_item >= 0 && cur_item < MaxNumItems)
            return text_lose[cur_item];
        else
            return "";
    }

    public int cur_value()
    {
        if (cur_item >= 0 && cur_item < MaxNumItems)
            return value[cur_item];
        else
            return 0;
    }


}
